package com.example.demo.service.impl;

import com.example.demo.constant.StatusCode;
import com.example.demo.AI.ChatGLM3_6BService;

import com.example.demo.dao.*;
import com.example.demo.entity.DTO.DialogueDTO;
import com.example.demo.entity.DTO.DialogueHistoryDTO;

import com.example.demo.entity.PO.DialoguePO;
import com.example.demo.entity.VO.chat.DialogueCriteriaVO;
import com.example.demo.entity.VO.chat.DialogueVO;
import com.example.demo.entity.VO.chat.MessageVO;
import com.example.demo.enums.SenderTypeEnum;
import com.example.demo.exception.UserClientException;
import com.example.demo.service.UserService;
import com.example.demo.utils.CommonConstant;
import com.example.demo.utils.JWTUtils;
import com.example.demo.service.DialogueService;
import com.google.gson.Gson;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Log4j
public class DialogueServiceImpl implements DialogueService {



    private final JWTUtils jwtUtils;

    private final DialogueMapper dialogueMapper;

    private final UserService userService;

    private final ChatGLM3_6BService chatGLM3_6BService;


    @Autowired
    public DialogueServiceImpl(DialogueMapper dialogueMapper,
                               JWTUtils jwtUtils, UserService userService, ChatGLM3_6BService chatGLM36BService){

        this.dialogueMapper = dialogueMapper;
        this.jwtUtils = jwtUtils;
        this.userService = userService;
        chatGLM3_6BService = chatGLM36BService;
    }


    @Override
    public List<DialogueVO> batchGetDialogue(DialogueCriteriaVO dialogueCriteriaVO) {
        List<DialoguePO> dialoguePOList = dialogueMapper.batchGetDialogue(dialogueCriteriaVO.getPetId(),dialogueCriteriaVO.getUserId(),dialogueCriteriaVO.getCursor(), dialogueCriteriaVO.getSize());
        List<DialogueVO> dialogueVOList = dialoguePOList.stream().map(dialoguePO -> DialogueVO.builder()
                .id(dialoguePO.getId())
                .userId(dialoguePO.getUserId())
                .petId(dialoguePO.getPetId())
                .dialogueNo(dialoguePO.getDialogueNo())
                .createdAt(dialoguePO.getCreatedAt())
                .dialogue(new Gson().fromJson(dialoguePO.getDialogue(), DialogueDTO.class))
                .build()).collect(Collectors.toList());

        return dialogueVOList;
    }

    @Override
    public void restartDialogue(Integer botId, Integer userId) {
        dialogueMapper.deleteDialogueOfUser(botId, userId);
    }

    @Override
    public DialogueVO sendMessage(MessageVO messageVO) {

        String prompt = CommonConstant.DEFAULT_PROMPT;

        //获取并处理历史记录
        List<String> dialogueHistoryJsonList = dialogueMapper.getDialogueHistory(messageVO.getPetId(), messageVO.getUserId(), CommonConstant.DIALOGUE_HISTORY_SIZE);
        Collections.reverse(dialogueHistoryJsonList);
        List<DialogueHistoryDTO> dialogueHistoryDTOList = new ArrayList<>();

        dialogueHistoryDTOList.add(DialogueHistoryDTO.builder()
                        .role(SenderTypeEnum.SYSTEM)
                        .content(prompt)
                .build());

        for (String dialogueHistoryJson : dialogueHistoryJsonList) {
            DialogueDTO dialogueDTO = new Gson().fromJson(dialogueHistoryJson, DialogueDTO.class);
            dialogueHistoryDTOList.add(DialogueHistoryDTO.builder()
                            .role(SenderTypeEnum.USER)
                            .content(dialogueDTO.getQuestion())
                    .build());
            dialogueHistoryDTOList.add(DialogueHistoryDTO.builder()
                            .role(SenderTypeEnum.BOT)
                            .content(dialogueDTO.getAnswer())
                    .build());
        }
        dialogueHistoryDTOList.add(DialogueHistoryDTO.builder()
                        .role(SenderTypeEnum.USER)
                        .content(messageVO.getMessage())
                .build());




        String answer = chatGLM3_6BService.sendChatRequest(dialogueHistoryDTOList);

        DialogueDTO dialogueDTOToReturn = DialogueDTO.builder()
                .question(messageVO.getMessage())
                .answer(answer)
                .build();

        DialoguePO dialoguePO = DialoguePO.builder()
                .userId(messageVO.getUserId())
                .petId(messageVO.getPetId())
                .dialogueNo(dialogueMapper.getDialogueAmount(messageVO.getPetId(), messageVO.getUserId()) + 1)
                .dialogue(new Gson().toJson(dialogueDTOToReturn))
                .createdAt(System.currentTimeMillis())
                .build();

        dialogueMapper.saveDialogue(dialoguePO);


        return DialogueVO.builder()
                .id(dialoguePO.getId())
                .userId(dialoguePO.getUserId())
                .petId(dialoguePO.getPetId())
                .dialogueNo(dialoguePO.getDialogueNo())
                .createdAt(dialoguePO.getCreatedAt())
                .dialogue(dialogueDTOToReturn)
                .build();
    }

    @Override
    public DialogueVO changeAnswer(Integer dialogueId) {
        DialoguePO originalDialogue = dialogueMapper.getDialogueById(dialogueId);
        Integer userId = jwtUtils.getUserId();
        if (Objects.isNull(originalDialogue) || originalDialogue.getEnable() == 0) {
            log.warn("用户试图将不属于自己的对话更改回答，userId:" + userId + ", dialogueId:" + dialogueId);
            throw new UserClientException(StatusCode.PARAMETER_ERROR.getKey(), "请不要修改对话id为不存在的id");
        }
        //检查用户更换的对话是否为自己的对话
        jwtUtils.checkUserIdOfJWT(originalDialogue.getUserId());
        dialogueMapper.disableDialogueById(dialogueId);
        DialogueDTO originalDialogueDTO = new Gson().fromJson(originalDialogue.getDialogue(), DialogueDTO.class);
        return sendMessage(MessageVO
                .builder()
                .userId(userId)
                .petId(originalDialogue.getPetId())
                .dialogueNo(originalDialogue.getDialogueNo())
                .message(originalDialogueDTO.getQuestion())
                .build());
    }

    @Override
    public Integer getDialogueAmount(Integer petId, Integer userId) {
        return dialogueMapper.getDialogueAmount(petId, userId);
    }


}
